#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/types.h>
#include <linux/spi/spidev.h>

#define SPI_DEVICE "/dev/spidev0.0"
#define SPI_MODE 0
#define SPI_BITS_PER_WORD 8
#define SPI_SPEED 500000

int spi_fd;

int spi_init() {
    int ret;
    spi_fd = open(SPI_DEVICE, O_RDWR);
    if (spi_fd < 0) {
        perror("Failed to open SPI device");
        return -1;
    }

    ret = ioctl(spi_fd, SPI_IOC_WR_MODE, &SPI_MODE);
    if (ret == -1) {
        perror("Failed to set SPI mode");
        return -1;
    }

    ret = ioctl(spi_fd, SPI_IOC_WR_BITS_PER_WORD, &SPI_BITS_PER_WORD);
    if (ret == -1) {
        perror("Failed to set bits per word");
        return -1;
    }

    ret = ioctl(spi_fd, SPI_IOC_WR_MAX_SPEED_HZ, &SPI_SPEED);
    if (ret == -1) {
        perror("Failed to set max speed Hz");
        return -1;
    }

    return 0;
}

int spi_transfer(unsigned char *tx_buf, unsigned char *rx_buf, size_t len) {
    struct spi_ioc_transfer tr = {
        .tx_buf = (unsigned long)tx_buf,
        .rx_buf = (unsigned long)rx_buf,
        .len = len,
        .speed_hz = SPI_SPEED,
        .bits_per_word = SPI_BITS_PER_WORD,
    };

    int ret = ioctl(spi_fd, SPI_IOC_MESSAGE(1), &tr);
    if (ret < 1) {
        perror("Failed to send SPI message");
        return -1;
    }

    return 0;
}

void spi_close() {
    close(spi_fd);
}

int main() {
    if (spi_init() != 0) {
        fprintf(stderr, "SPI initialization failed\n");
        return -1;
    }

    unsigned char tx_buf[10] = {0};
    unsigned char rx_buf[10] = {0};

    // Example data to send
    tx_buf[0] = 0x01; // Example command
    tx_buf[1] = 0x02; // Example data

    if (spi_transfer(tx_buf, rx_buf, sizeof(tx_buf)) != 0) {
        fprintf(stderr, "SPI transfer failed\n");
        spi_close();
        return -1;
    }

    printf("Received data: ");
    for (size_t i = 0; i < sizeof(rx_buf); i++) {
        printf("%02X ", rx_buf[i]);
    }
    printf("\n");

    spi_close();
    return 0;
}